﻿// (c) Copyright slimCODE Software Inc. - www.slimcode.com
// This source is subject to the Microsoft Public License (Ms-PL).
// Please see http://go.microsoft.com/fwlink/?LinkID=131993 for details.
// All other rights reserved.

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Globalization;

namespace SlimCode.SlimPasswords
{
  class PasswordItem : LaunchableItem
  {
    private bool m_suspendDateUpdates; // = false

    public PasswordItem( PasswordStore store )
    {
      if( store == null )
        throw new ArgumentNullException( "store" );

      m_store = store;
    }

    public PasswordItem( PasswordStore store, string name )
      : base( name )
    {
      if( store == null )
        throw new ArgumentNullException( "store" );

      m_store = store;
    }

    #region Category PROPERTY

    private string m_category = string.Empty;

    public string Category
    {
      get { return m_category; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_category )
        {
          m_category = value;
          this.OnCategoryChanged();
        }
      }
    }

    protected virtual void OnCategoryChanged()
    {
      this.LastModified = DateTime.Now;
      m_name = null;
    }

    #endregion

    #region Created PROPERTY

    public DateTime Created
    {
      get; private set;
    }

    #endregion

    #region Description PROPERTY

    public override string Description
    {
      get { return string.Empty; }
    }

    #endregion

    #region Email PROPERTY

    private string m_email = string.Empty;

    public string Email
    {
      get { return m_email; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_email )
        {
          m_email = value;
          this.OnEmailChanged();
        }
      }
    }

    protected virtual void OnEmailChanged()
    {
      this.LastModified = DateTime.Now;
    }

    #endregion

    #region LastModified PROPERTY

    public DateTime LastModified
    {
      get; private set;
    }

    #endregion

    #region Name PROPERTY

    private string m_name;

    public override string Name
    {
      get 
      {
        if( m_name == null )
        {
          // TODO: Support patterns
          m_name = this.Category + " : " + this.Title;
        }

        return m_name;
      }
    }

    #endregion

    #region Notes PROPERTY

    private string m_notes = string.Empty;

    public string Notes
    {
      get { return m_notes; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_notes )
        {
          m_notes = value;
          this.OnNotesChanged();
        }
      }
    }

    protected virtual void OnNotesChanged()
    {
      this.LastModified = DateTime.Now;
    }

    #endregion

    #region Password PROPERTY

    private string m_password = string.Empty;

    public string Password
    {
      get { return m_password; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_password )
        {
          m_password = value;
          this.OnPasswordChanged();
        }
      }
    }

    protected virtual void OnPasswordChanged()
    {
      this.LastModified = DateTime.Now;
    }

    #endregion

    #region PreviousPassword PROPERTY

    private string m_previousPassword = string.Empty;

    public string PreviousPassword
    {
      get { return m_previousPassword; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_previousPassword )
        {
          m_previousPassword = value;
          this.OnPreviousPasswordChanged();
        }
      }
    }

    protected virtual void OnPreviousPasswordChanged()
    {
      // Does not affect LastModified
    }

    #endregion

    #region Store PROPERTY

    private PasswordStore m_store;

    public PasswordStore Store
    {
      get { return m_store; }
    }

    #endregion

    #region UrlAddress PROPERTY

    private string m_urlAddress = string.Empty;

    public string UrlAddress
    {
      get { return m_urlAddress; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_urlAddress )
        {
          m_urlAddress = value;
          this.OnUrlAddressChanged();
        }
      }
    }

    protected virtual void OnUrlAddressChanged()
    {
      this.LastModified = DateTime.Now;
    }

    #endregion

    #region UserName PROPERTY

    private string m_userName = string.Empty;

    public string UserName
    {
      get { return m_userName; }
      set
      {
        if( value == null )
          value = string.Empty;

        if( value != m_userName )
        {
          m_userName = value;
          this.OnUserNameChanged();
        }
      }
    }

    protected virtual void OnUserNameChanged()
    {
      this.LastModified = DateTime.Now;
    }

    #endregion

    public override bool Load( XmlNode parentNode )
    {
      if( !base.Load( parentNode ) )
        return false;

      m_suspendDateUpdates = true;

      try
      {
        XmlNode valueNode = parentNode.SelectSingleNode( "Category" );

        if( valueNode != null )
        {
          this.Category = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "UserName" );

        if( valueNode != null )
        {
          this.UserName = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "Email" );

        if( valueNode != null )
        {
          this.Email = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "Password" );

        if( valueNode != null )
        {
          m_password = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "PreviousPassword" );

        if( valueNode != null )
        {
          m_previousPassword = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "UrlAddress" );

        if( valueNode != null )
        {
          this.UrlAddress = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "Notes" );

        if( valueNode != null )
        {
          this.Notes = valueNode.InnerText;
        }

        valueNode = parentNode.SelectSingleNode( "Created" );

        if( valueNode != null )
        {
          /* Uncomment once I use XmlConvert in desktop app
          try
          {
            this.Created = XmlConvert.ToDateTime( valueNode.InnerText, XmlDateTimeSerializationMode.Utc );
          }
          catch*/
          {
            try
            {
              this.Created = DateTime.Parse( valueNode.InnerText, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None );
            }
            catch { }
          }
        }

        valueNode = parentNode.SelectSingleNode( "LastModified" );

        if( valueNode != null )
        {
          /* Uncomment once I use XmlConvert in desktop app
          try
          {
            this.LastModified = XmlConvert.ToDateTime( valueNode.InnerText, XmlDateTimeSerializationMode.Utc );
          }
          catch*/
          {
            try
            {
              this.LastModified = DateTime.Parse( valueNode.InnerText, DateTimeFormatInfo.InvariantInfo, DateTimeStyles.None );
            }
            catch { }
          }
        }
      }
      finally
      {
        m_suspendDateUpdates = false;
      }

      return true;
    }

    public override void Save( XmlWriter writer )
    {
      // Saves LastLaunchCommand, Active and Title.
      base.Save( writer );

      // Only write non-empty strings to save space.
      if( this.Category.Length > 0 )
      {
        writer.WriteElementString( "Category", this.Category );
      }

      if( this.UserName.Length > 0 )
      {
        writer.WriteElementString( "UserName", this.UserName );
      }

      if( this.Email.Length > 0 )
      {
        writer.WriteElementString( "Email", this.Email );
      }

      if( this.Password.Length > 0 )
      {
        writer.WriteElementString( "Password", this.Password );
      }

      if( this.PreviousPassword.Length > 0 )
      {
        writer.WriteElementString( "PreviousPassword", this.PreviousPassword );
      }

      if( this.UrlAddress.Length > 0 )
      {
        writer.WriteElementString( "UrlAddress", this.UrlAddress );
      }

      if( this.Notes.Length > 0 )
      {
        writer.WriteElementString( "Notes", this.Notes );
      }

      /* Stupid me for not using XmlConvert in desktop version
      writer.WriteElementString( "Created", XmlConvert.ToString( this.CreatedDate, XmlDateTimeSerializationMode.Utc ) );
      writer.WriteElementString( "LastModified", XmlConvert.ToString( this.LastModifiedDate, XmlDateTimeSerializationMode.Utc ) );
      */
      writer.WriteElementString( "Created", this.Created.ToString( DateTimeFormatInfo.InvariantInfo ) );
      writer.WriteElementString( "LastModified", this.LastModified.ToString( DateTimeFormatInfo.InvariantInfo ) );
    }

    protected override void OnTitleChanged()
    {
      this.LastModified = DateTime.Now;
      m_name = null;
    }
  }
}
